﻿// Copyright 2013 Ronald Schlenker, www.technewlogic.de.
// 
// This file is part of Byond.
// 
// Byond is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
// 
// Byond is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Byond.  If not, see <http://www.gnu.org/licenses/>.
using System;
using System.IO;
using System.Linq;
using Byond.AudioMidi;
using Byond.Logging;

namespace Byond.Recording
{
	public class AudioRecorder : IDisposable
	{
		private readonly string _rootPath;
		private readonly Lazy<IAudioInfo> _audioInfo;
		private readonly IUserLogger _logger;

		private MergedChannelsWaveFileWriter _writer;

		public AudioRecorder(Env env)
		{
			_rootPath = env.RecordingsPath;
			if (!Directory.Exists(_rootPath))
				Directory.CreateDirectory(_rootPath);
		}

		public bool IsWriting { get { return _writer != null; } }

		public void ReStart()
		{
			lock (this)
			{
				DisposeCurrentWriter();

				// TODO: Channels
				var recordingFile = Path.Combine(_rootPath, GetNextFileName());
				_logger.Log("Recording started: " + recordingFile);
				_writer = new MergedChannelsWaveFileWriter(
					(int)_audioInfo.Value.SampleRate,
					2,
					recordingFile);
			}
		}

		public void Stop()
		{
			lock (this)
				DisposeCurrentWriter();
		}

		public void Write(double[][] channelValues)
		{
			lock (this)
			{
				if (!IsWriting)
					return;
				_writer.Write(channelValues);
			}
		}

		private string GetNextFileName()
		{
			var dateTimeString = DateTime.Now.ToString("yyyy-MM-dd_");
			var existingFiles = Directory.GetFiles(_rootPath)
				.Select(Path.GetFileName)
				.Where(it => it.StartsWith(dateTimeString))
				.Where(it => it.EndsWith(".wav"))
				.OrderBy(it => it)
				.ToList();
			var count = existingFiles.Count;

			while (true)
			{
				var desiredFileName = dateTimeString + count.ToString("D4");
				if (Directory.GetFiles(_rootPath).Any(it => it.StartsWith(desiredFileName)))
					count++;
				else
					return desiredFileName;
			}
		}

		private void DisposeCurrentWriter()
		{
			if (_writer == null)
				return;
			_logger.Log("Recording stopped.");
			_writer.Dispose();
			_writer = null;
		}

		public void Dispose()
		{
			lock (this)
				DisposeCurrentWriter();
		}
	}
}
